<!-- ImageCropper.vue -->
<template>
  <div class="cropper-container">
    <div class="cropper-content" ref="cropperContent">
      <canvas ref="canvas" width="400" height="400"></canvas>

      <!-- 可拖动的裁剪框 -->
      <div class="cropper-selection" :style="{
        left: selection.left + 'px',
        top: selection.top + 'px',
        width: selection.width + 'px',
        height: selection.height + 'px'
      }" @mousedown.prevent="startDrag" @touchstart.prevent="startDrag">
        <div class="corner top-left" @mousedown.stop="(e) => startResize('top-left', e)"
          @touchstart.stop="(e) => startResize('top-left', e)"></div>
        <div class="corner top-right" @mousedown.stop="(e) => startResize('top-right', e)"
          @touchstart.stop="(e) => startResize('top-right', e)"></div>
        <div class="corner bottom-left" @mousedown.stop="(e) => startResize('bottom-left', e)"
          @touchstart.stop="(e) => startResize('bottom-left', e)"></div>
        <div class="corner bottom-right" @mousedown.stop="(e) => startResize('bottom-right', e)"
          @touchstart.stop="(e) => startResize('bottom-right', e)"></div>
      </div>
    </div>
    <div class="cropper-header">
      <button class="cancel-btn" @click="cancel">取消</button>
      <button class="confirm-btn" @click="confirm">确定</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'

const props = defineProps({
  imageSrc: {
    type: String,
    required: true
  }
})
const model = defineModel()

const emit = defineEmits(['confirm', 'cancel'])

const canvas = ref(null)
const cropperContent = ref(null)
const selection = ref({
  left: 100,
  top: 100,
  width: 200,
  height: 200
})

let isDragging = false
let isResizing = false
let resizeDirection = ''
let startX, startY
let startLeft, startTop
let startWidth, startHeight

// 初始化画布
const initCanvas = () => {
  const ctx = canvas.value.getContext('2d')
  const img = new Image()
  img.onload = () => {
    // 获取canvas的实际显示尺寸
    const rect = canvas.value.getBoundingClientRect()
    const displayWidth = rect.width
    const displayHeight = rect.height
    
    // 设置canvas的实际尺寸与显示尺寸一致
    canvas.value.width = displayWidth
    canvas.value.height = displayHeight
    
    // 绘制原图，保持比例
    ctx.drawImage(img, 0, 0, displayWidth, displayHeight)
    
    // 更新selection的初始位置，使其居中
    const selectionSize = Math.min(displayWidth, displayHeight) * 0.5
    selection.value = {
      left: (displayWidth - selectionSize) / 2,
      top: (displayHeight - selectionSize) / 2,
      width: selectionSize,
      height: selectionSize
    }
  }
  img.src = props.imageSrc
}

// 获取事件坐标（兼容鼠标和触摸事件）
const getEventPosition = (e) => {
  if (e.touches && e.touches.length > 0) {
    return {
      x: e.touches[0].clientX,
      y: e.touches[0].clientY
    }
  }
  return {
    x: e.clientX,
    y: e.clientY
  }
}

// 开始拖拽裁剪框
const startDrag = (e) => {
  // 如果点击的是 corner，跳过拖拽
  if (e.target.classList.contains('corner')) return

  isDragging = true
  const pos = getEventPosition(e)
  startX = pos.x
  startY = pos.y
  startLeft = selection.value.left
  startTop = selection.value.top
}

// 开始调整裁剪框大小
const startResize = (direction, e) => {
  isResizing = true
  resizeDirection = direction
  const pos = getEventPosition(e)
  startX = pos.x
  startY = pos.y
  startLeft = selection.value.left
  startTop = selection.value.top
  startWidth = selection.value.width
  startHeight = selection.value.height
  e.preventDefault() // 防止默认行为
  e.stopPropagation() // 阻止事件冒泡
}

// 处理鼠标/触摸移动
const handleMove = (e) => {
  const pos = getEventPosition(e)
  
  // 获取canvas的实际尺寸
  const canvasWidth = canvas.value.width
  const canvasHeight = canvas.value.height

  if (isDragging) {
    const dx = pos.x - startX
    const dy = pos.y - startY

    // 计算新位置，确保不超出边界
    let newLeft = startLeft + dx
    let newTop = startTop + dy

    // 限制在容器内
    newLeft = Math.max(0, Math.min(newLeft, canvasWidth - selection.value.width))
    newTop = Math.max(0, Math.min(newTop, canvasHeight - selection.value.height))

    selection.value.left = newLeft
    selection.value.top = newTop
    console.log('更新位置:', { newLeft, newTop })
  } else if (isResizing) {
    const dx = pos.x - startX
    const dy = pos.y - startY

    let newLeft = startLeft
    let newTop = startTop
    let newWidth = startWidth
    let newHeight = startHeight

    // 根据调整方向计算新的位置和大小
    switch (resizeDirection) {
      case 'top-left':
        newLeft = Math.min(startLeft + dx, startLeft + startWidth - 50)
        newTop = Math.min(startTop + dy, startTop + startHeight - 50)
        newWidth = startWidth - dx
        newHeight = startHeight - dy
        break
      case 'top-right':
        newTop = Math.min(startTop + dy, startTop + startHeight - 50)
        newWidth = Math.max(50, startWidth + dx)
        newHeight = startHeight - dy
        break
      case 'bottom-left':
        newLeft = Math.min(startLeft + dx, startLeft + startWidth - 50)
        newWidth = startWidth - dx
        newHeight = Math.max(50, startHeight + dy)
        break
      case 'bottom-right':
        newWidth = Math.max(50, startWidth + dx)
        newHeight = Math.max(50, startHeight + dy)
        break
    }

    // 确保不超出容器边界
    if (newLeft < 0) {
      newWidth += newLeft
      newLeft = 0
    }
    if (newTop < 0) {
      newHeight += newTop
      newTop = 0
    }
    if (newLeft + newWidth > canvasWidth) {
      newWidth = canvasWidth - newLeft
    }
    if (newTop + newHeight > canvasHeight) {
      newHeight = canvasHeight - newTop
    }

    // 确保最小尺寸
    newWidth = Math.max(50, newWidth)
    newHeight = Math.max(50, newHeight)

    selection.value.left = newLeft
    selection.value.top = newTop
    selection.value.width = newWidth
    selection.value.height = newHeight
  }
}

// 结束拖拽或调整大小
const handleEnd = () => {
  isDragging = false
  isResizing = false
}

// 确定裁剪
const confirm = () => {
  const ctx = canvas.value.getContext('2d')
  
  // 获取canvas的实际显示尺寸
  const rect = canvas.value.getBoundingClientRect()
  const displayWidth = rect.width
  const displayHeight = rect.height
  
  // 重新加载原始图片以获取完整分辨率
  const img = new Image()
  img.onload = () => {
    // 计算缩放比例
    const scaleX = img.width / displayWidth
    const scaleY = img.height / displayHeight
    
    // 计算在原图上的实际裁剪区域
    const cropX = selection.value.left * scaleX
    const cropY = selection.value.top * scaleY
    const cropWidth = selection.value.width * scaleX
    const cropHeight = selection.value.height * scaleY
    
    // 创建临时画布来存储裁剪结果
    const tempCanvas = document.createElement('canvas')
    const tempCtx = tempCanvas.getContext('2d')
    tempCanvas.width = cropWidth
    tempCanvas.height = cropHeight
    
    // 从原图绘制选区内容到临时画布
    tempCtx.drawImage(
      img,
      cropX, cropY, cropWidth, cropHeight,
      0, 0, cropWidth, cropHeight
    )
    
    // 转换为URL
    const dataUrl = tempCanvas.toDataURL('image/png')
    
    emit('confirm', dataUrl)
    model.value = false
  }
  img.src = props.imageSrc
}

// 取消
const cancel = () => {
  emit('cancel')
  model.value = false
}

// 监听imageSrc变化，重新初始化画布
watch(() => props.imageSrc, () => {
  if (props.imageSrc && canvas.value) {
    initCanvas()
  }
})

onMounted(() => {
  initCanvas()
  // 添加鼠标事件监听器
  window.addEventListener('mousemove', handleMove)
  window.addEventListener('mouseup', handleEnd)

  // 添加触摸事件监听器
  window.addEventListener('touchmove', handleMove, { passive: false })
  window.addEventListener('touchend', handleEnd)
})

// 清理事件
onUnmounted(() => {
  // 移除鼠标事件监听器
  window.removeEventListener('mousemove', handleMove)
  window.removeEventListener('mouseup', handleEnd)

  // 移除触摸事件监听器
  window.removeEventListener('touchmove', handleMove)
  window.removeEventListener('touchend', handleEnd)
})
</script>

<style lang="scss" scoped>
.cropper-container {
  @include fixed-top;
  width: 100%;
  height: 100%;
  background-color: #000;
  @include flex-center;
  flex-direction: column;
  touch-action: none;
  /* 防止触摸时页面滚动 */
}

.cropper-header {
  display: flex;
  gap: 10px;
  margin-top: 30px;
}

button {
  padding: 8px 16px;
  background: #fff;
  color: #000;
  cursor: pointer;
  font-size: 14px;
  border-radius: $border-radius-sm;

  &.cancel-btn {
    background: #ff4d4f;
    color: #fff;
  }

  &.confirm-btn {
    background: #0099ff;
    color: #fff;
  }
}

.cropper-content {
  width: 100%;

  height: 300px;
  background: #ccc;
  position: relative;
  overflow: hidden;
}

canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.cropper-selection {
  position: absolute;
  border: 2px solid #0099ff;
  background: rgba(0, 153, 255, 0.2);
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
  cursor: move;
  z-index: 10;
  user-select: none;
  /* 防止文本选择干扰拖拽 */
  pointer-events: auto;
  /* 确保可以接收鼠标事件 */
}

.corner {
  position: absolute;
  width: 16px;
  height: 16px;
  background: #0099ff;
  border: 2px solid white;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  cursor: pointer;
  z-index: 11;
  pointer-events: auto;
  /* 确保可以接收鼠标事件 */
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
}

.top-left {
  top: 0;
  left: 0;
  cursor: nw-resize;
}

.top-right {
  top: 0;
  right: -14px;
  cursor: ne-resize;
}

.bottom-left {
  bottom: -14px;
  left: 0;
  cursor: sw-resize;
}

.bottom-right {
  bottom: -15px;
  right: -15px;
  cursor: se-resize;
}
</style>